//
// Created by HJ on 2024-08-25.
//

#include "XMap.h"



bool XMap::init(JNIEnv *pEnv) {
    env_ = pEnv;
    return true;
}

std::map<std::string, std::string> XMap::convertJavaHashMapToCppMap(jobject jMap) {
    std::map<std::string, std::string> cMap;

    jclass hashMapClass = env_->FindClass("java/util/HashMap");
    jmethodID keySetMethod = env_->GetMethodID(hashMapClass, "keySet", "()Ljava/util/Set;");
    jmethodID getMethod = env_->GetMethodID(hashMapClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
    jobject keySetObject = env_->CallObjectMethod(jMap, keySetMethod);
    jclass setClass = env_->FindClass("java/util/Set");
    jmethodID iteratorMethod = env_->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
    jobject iteratorObject = env_->CallObjectMethod(keySetObject, iteratorMethod);
    jclass iteratorClass = env_->FindClass("java/util/Iterator");
    jmethodID hasNextMethod = env_->GetMethodID(iteratorClass, "hasNext", "()Z");
    jmethodID nextMethod = env_->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
    while (env_->CallBooleanMethod(iteratorObject, hasNextMethod)) {
        jobject keyObject = env_->CallObjectMethod(iteratorObject, nextMethod);
        jstring keyString = static_cast<jstring>(env_->CallObjectMethod(keyObject, env_->GetMethodID(env_->GetObjectClass(keyObject), "toString", "()Ljava/lang/String;")));
        jstring valueString = static_cast<jstring>(env_->CallObjectMethod(jMap, getMethod, keyObject));
        const char* keyChars = env_->GetStringUTFChars(keyString, nullptr);
        const char* valueChars = env_->GetStringUTFChars(valueString, nullptr);
        cMap[std::string(keyChars)] = std::string(valueChars);
        env_->ReleaseStringUTFChars(keyString, keyChars);
        env_->ReleaseStringUTFChars(valueString, valueChars);
        env_->DeleteLocalRef(keyObject);
        env_->DeleteLocalRef(keyString);
        env_->DeleteLocalRef(valueString);
    }
    env_->DeleteLocalRef(keySetObject);
    env_->DeleteLocalRef(iteratorObject);
    
    return cMap;
}

jobject XMap::convertCppMapToJavaHashMap(std::map<std::string, std::string> cMap) {
    jclass hashMapClass = env_->FindClass("java/util/HashMap");
    jmethodID initMethod = env_->GetMethodID(hashMapClass, "<init>", "()V");
    jmethodID putMethod = env_->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
    jobject hashMapObject = env_->NewObject(hashMapClass, initMethod);
    for (const auto& pair : cMap) {
        jstring key = env_->NewStringUTF(pair.first.c_str());
        jstring value = env_->NewStringUTF(pair.second.c_str());
        env_->CallObjectMethod(hashMapObject, putMethod, key, value);
        env_->DeleteLocalRef(key);
        env_->DeleteLocalRef(value);
    }
    return hashMapObject;
}
